package com.its.common.net.core.util;

import cn.hutool.core.lang.Singleton;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ReflectUtil;
import io.netty.util.internal.PlatformDependent;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicLong;
/**
 * @Author xiaxp
 * @Date 9/13/22 15:50
 * @Description
 */
@Slf4j
public class DirectMemReporter{
    private static final int _1KB = 1024;
    private int interval;
    private AtomicLong directMemCounter;

    private DirectMemReporter(int interval){
        this.interval = interval;
    }

    /**
     * 获取堆外内存检测器单例
     * @param interval 检测间隔, 单位毫秒
     * @return 堆外内存检测器
     */
    public static DirectMemReporter getInstance(int interval){
        return Singleton.get(DirectMemReporter.class, interval);
    }

    private void init(){

        Field field = ReflectUtil.getField(PlatformDependent.class, "DIRECT_MEMORY_COUNTER");
        field.setAccessible(true);

        try {
            directMemCounter = (AtomicLong) field.get(PlatformDependent.class);
        } catch (IllegalAccessException e) {
        }
    }

    public void startReport(){
        init();

        ThreadUtil.schedule(new ScheduledThreadPoolExecutor(1),
                () -> doReport(),
                5000L,
                interval,
                true);
    }

    private void doReport() {
        int memKb = (int) (directMemCounter.get() / _1KB);
        log.info("Netty堆外内存: {} k", memKb);
        //默认一个Chunk16M
    }
}
